/*===========================================================
 
 .---=||||[ B L O O D Y ]|||||=====================----------....
 |                                                              |
 |    THE  M O S T   B L O O D Y  GAME EVER!                    |
 |                                                              |
 |    bloody harvest is coming... soon,                         |
 |                                              heil Satan!     |
 !                                                              !
 .                                                              ,
  ~~~~-------------================================|||||||||==-~




 Name-Space: {core, logic, editor}
 Module: {draw, coll, scgr, ...}
 Class: <name of class>
 Last modification:  <author>, <time>

 TODO:
 <-------- todo #1 ---------->
 <-------- todo #2 ---------->
 <-------- todo #3 ---------->
        ............
 <-------- todo #n ---------->

 FIX:
 <-------- fix #1 ----------->
 <-------- fix #1 ----------->
         ..........
 <-------- fix #n ----------->




 
 
 ============================================================*/
#ifndef IMAGE_H_
#define IMAGE_H_

#include "common.h"

namespace core
{
    namespace draw
    {

		/**
		 * Class representing image. This class uses OpenIL for loading
		 * image.
		 */
		class Image
		{
		public:
			/**
			 *  Possible image formats, that are accepted by this class.
			 */
			enum ImageType{
				RGB8 = 1, RGBA8, GREY8, GRAY16
			};
		
		private:
			/**
			 *  Bitmap data
			 */
			unsigned char *bitmap;

			/**
			 * Width of image
			 */
			unsigned width;

			/**
			 * Height of image
			 */
			unsigned height;

			/**
			 * Image data format.
			 */
			ImageType type;

		public:
			/**
			 *  Null constructor
			 */
			Image(){ bitmap = 0; };

			/**
			 * Creates new image from file
			 */
			Image(const char* filename){ load(filename); };

			/**
			 * Gets gray pixel at x, y
			 * 
			 * @param x X position of pixel
			 * @param y Y position of pixel
			 * @return Approximatly value of gray pixel.
			 * 
			 * @note This is just simple method how to get gray pixel,
			 * from TrueColor image. Note taht this method compute value
			 * of image as (R+G+B)/3, this is not correct for human 
			 * perception of brightness of pixel [R,G,B].
			 */
			unsigned int getGrey(unsigned x, unsigned y){
				if (RGB8 == type){
					unsigned ptr = (y * width + x) * 3;
					return (bitmap[ptr] + bitmap[ptr + 1] + bitmap[ptr + 2]) / 3;
				}
				else if (RGBA8 == type){
					unsigned ptr = (y * width + x) * 4;
					return (bitmap[ptr] + bitmap[ptr + 1] + bitmap[ptr + 2] + bitmap[ptr + 3]) / 4;
				}
				else if (GREY8 == type){
					unsigned ptr = y * width + x;
					return bitmap[ptr];
				}
				else {
					unsigned ptr = (y * width + x) * 2;
					return (bitmap[ptr] << 8) + bitmap[ptr + 1];
				}
				return 0;
			};
		
			/**
			 *  Gets RGB at x,y from image.
			 * 
			 * @param x X position of pixel.
			 * @param y Y position of pixel
			 * 
			 * @return Value of RGB quad as:
			 * R G B for RGB8 format or
			 * R G B A for RGBA format.
			 * 
			 * @note To decode to value of pixels, you should know,
			 * that R G B values of pixel are encoded in returned 
			 * value as bytes in this order:
			 * 
			 * for RGB8: 00rrggbb,
			 * for RGBA8: rrggbbaa.
			 */
			unsigned int getRGB(unsigned x, unsigned y){
				if (RGB8 == type){
					unsigned ptr = (y * width + x) * 3;
					return bitmap[ptr] << 16 + bitmap[ptr + 1] << 8+ bitmap[ptr + 2];
				}
				else if (RGBA8 == type){
					unsigned ptr = (y * width + x) * 4;
					return bitmap[ptr] << 24 + bitmap[ptr + 1] << 16 + bitmap[ptr + 2] << 8 + bitmap[ptr + 3];
				}
				else if (GREY8 == type){
					unsigned ptr = y * width + x;
					unsigned short val = bitmap[ptr];
					return val << 16 + val << 8 + val;
				}
				else {
					unsigned ptr = (y * width + x) * 2;
					return (bitmap[ptr] + bitmap[ptr + 1]) / 2;
				}
				return 0;
		
			};

			/**
			 * Gets image bitmap bitmap data
			 * 
			 * @return Pointer to internal bitmap.
			 */
			unsigned char* getBitmap(){
				return bitmap;
			};
		
			/**
			 * Gets image format type
			 * 
			 * @return Format of image data
			 */
			ImageType getType(){ return type; };


			/**
			 * Gets image width
			 * 
			 * @return width of image.
			 */
			unsigned getWidth(){ return width; };

			/**
			 * Gets image height
			 * 
			 * @return height of image.
			 */
			unsigned getHeight(){ return height; };
		
			/**
			 * Gets image format type as OpenGL GLenum
			 * 
			 * @return Representation of current format in OpenGL GLenum.
			 */
			GLenum getGLType();
		
			/**
			 * Loads image from file
			 * 
			 * @param filename Path to file for loading
			 */
			void load(const char* filename);
		};
		
    }
}

#endif /*IMAGE_H_*/
